﻿using System;
using System.Collections.Generic;
using Battle.Engine.InputData;
using Battle.Engine.LogicModel;

namespace Battle.Engine
{
    public class ComputeCore : BaseCompute
    {
        public bool rounding = false;           //是否在回合中

        public double realTime = 0;         //不算暂停等待的真实时间,从0开始
        public double currentTime = 0;      //按时间片走的,战斗逻辑中的真实时间,从0开始

        public const double DELTA_TIME = 0.1; //战斗逻辑计算的最小时间间隔
        //public const double DELTA_AI = 0.1;     //AI的最小时间间隔

        public AI.EngineAI attackerAI = null;     //自动操作AI
        public AI.EngineAI defenderAI = null;
        public bool attackerAuto = false;       //是否自动操作
        public bool defenderAuto = false;       //

        protected bool autoFinishARound = false;   //内部变量,在没有技能进行的时候自动结束一回合
        protected bool end = false;                 //战斗结束

        protected bool isSkipping = false;

        public ComputeCore()
        {

        }

        public override void SetCallback(EngineCallback callback)
        {
            this.data.callback = callback;
        }

        public void SetData(InFightData idata)
        {
            this.data = new EngineData();
            this.data.init(idata, this);
            attackerAuto = idata.attacker.isAuto;
            defenderAuto = idata.defender.isAuto;

            if (idata.recordAttackerOperate == true)
            {
                this.data.attacker.record = true;
                this.data.attacker.recordSkills = new List<FOperateSkill>();
                this.data.attacker.recordTranss = new List<FOperateTrans>();
            }
            if (idata.recordDefenderOperate == true)
            {
                this.data.defender.record = true;
                this.data.defender.recordSkills = new List<FOperateSkill>();
                this.data.defender.recordTranss = new List<FOperateTrans>();
            }
        }

        public override void Start()
        {
            this.data.roundNum = 1;
            rounding = false;
            realTime = 0;
            currentTime = 0;
            end = false;

            BattleBegin();

            if (attackerAI != null)
            {
                attackerAI.Start(this.data, CampType.ATTACK, this);
            }
            if (defenderAI != null && defenderAuto)
            {
                defenderAI.Start(this.data, CampType.DEFENCE, this);
            }
        }

        public override void Pause()
        {
            if (attackerAI != null)
                attackerAI.Pause();
            if (defenderAI != null)
                defenderAI.Pause();
        }

        public override void Continue()
        {
            if (attackerAI != null)
                attackerAI.Continue();
            if (defenderAI != null)
                defenderAI.Continue();
        }

        public override void Stop()
        {
            if (attackerAI != null)
                attackerAI.Stop();
            if (defenderAI != null)
                defenderAI.Stop();
        }

        public override void NextRound()
        {
            data.ResetRound();

            data.roundTime = 0;
            rounding = true;
            this.autoFinishARound = false;

            RoundBegin();

            //ai
            if (attackerAI != null)
            {
                attackerAI.NextRound();
            }
            if (defenderAI != null)
            {
                defenderAI.NextRound();
            }
        }

        public override void FinishRound()
        {
            if(data.ultimateSkill != null && data.ultimateSkill.state != FSkillState.FINISH && data.ultimateSkill.state != FSkillState.LAST)
            {//回合结束时还有已经记录但是未被释放的大招，进行记录清除
                if (this.data.attacker.record == true)
                {
                    for (int i = (this.data.attacker.recordSkills.Count-1); i >= 0; i--)
                    {//从最后一个开始遍历，出问题的一般就是最后一个临界点释放的技能大招
                        var op = this.data.attacker.recordSkills[i];
                        if (op.camp == this.data.curRoundCamp
                            && op.uniquedId.Equals(data.ultimateSkill.actor.uniqueId)
                            && op.skillIndex == data.ultimateSkill.index
                            && op.round == this.data.roundNum)
                        {
                            this.data.attacker.recordSkills.Remove(op);
                            break;
                        }
                    }
                }
                if (this.data.defender.record == true)
                {
                    for (int i = (this.data.defender.recordSkills.Count - 1); i >= 0; i--)
                    {
                        var op = this.data.defender.recordSkills[i];
                        if (op.camp == this.data.curRoundCamp
                            && op.uniquedId.Equals(data.ultimateSkill.actor.uniqueId)
                            && op.skillIndex == data.ultimateSkill.index
                            && op.round == this.data.roundNum)
                        {
                            this.data.defender.recordSkills.Remove(op);
                            break;
                        }
                    }
                }
            }
            this.data.roundNum = this.data.roundNum + 1;
            rounding = false;
            
            RoundEnd();

            //检查回合数到最大,返回战斗结束
            if (this.data.roundNum > this.data.roundMax)
            {
                BattleEnd();
            }

            //ai
            if (attackerAI != null)
            {
                attackerAI.FinishRound();
            }
            if (defenderAI != null)
            {
                defenderAI.FinishRound();
            }
        }

        //使用技能
        public override void DoSkill(CampType camp, string uniqueId, int index)
        {
            if (this.end == true)
                return;
            if (rounding == false)
                return;

            bool isDo = false;
            if (camp == CampType.ATTACK && data.curRoundCamp == CampType.ATTACK)
            {
                foreach (var actor in data.attacker.actors)
                {
                    if (actor.uniqueId.Equals(uniqueId) == true)
                    {
                        isDo = actor.DoSkill(index, this.data);
                        break;
                    }
                }
            }
            else if (camp == CampType.DEFENCE && data.curRoundCamp == CampType.DEFENCE)
            {
                foreach (var actor in data.defender.actors)
                {
                    if (actor.uniqueId.Equals(uniqueId) == true)
                    {
                        isDo = actor.DoSkill(index, this.data);
                        break;
                    }
                }
            }

            //如果技能释放成功了,记录操作
            if (isDo == true)
            {
                FOperateSkill op = new FOperateSkill();
                op.camp = camp;
                op.uniquedId = uniqueId;
                op.skillIndex = index;
                op.round = data.roundNum;
                op.roundTime = data.roundTime;

                if (this.data.attacker.record == true)
                {
                    this.data.attacker.recordSkills.Add(op);
                }
                else if (this.data.defender.record == true)
                {
                    this.data.defender.recordSkills.Add(op);
                }
            }
        }

        //换阵
        public override void DoTrans(List<string> uids, List<int> fpids)
        {
            for (int i = 0; i < uids.Count; ++i) {
                var actor = data.GetActorByUID(uids[i]);
                actor.MainPosition.SetFPID(fpids[i]);
            }
            if (this.data.callback != null)
                this.data.callback.TransConfirm(uids, fpids);

            FOperateTrans op = new FOperateTrans();
            op.round = data.roundNum;
            op.uids = uids;
            op.fpids = fpids;
            if (this.data.attacker.record == true)
            {
                this.data.attacker.recordTranss.Add(op);
            }
            else if (this.data.defender.record == true)
            {
                this.data.defender.recordTranss.Add(op);
            }
        }

        public override void GetRecordOperates(CampType camp, out List<FOperateSkill> skills, out List<FOperateTrans> transs)
        {
            if (camp == CampType.ATTACK)
            {
                skills = this.data.attacker.recordSkills;
                transs = this.data.attacker.recordTranss;
            }
            else
            {
                skills = this.data.defender.recordSkills;
                transs = this.data.defender.recordTranss;
            }
        }

        public override void SetReplayOperates(CampType camp, List<FOperateSkill> skills, List<FOperateTrans> transs)
        {
            if (camp == CampType.ATTACK)
            {
                this.data.attacker.replaySkills = skills;
                this.data.attacker.replayTranss = transs;
            }
            else
            {
                this.data.defender.replaySkills = skills;
                this.data.defender.replayTranss = transs;
            }
        }

        public override bool Update(double deltaTime)
        {
            //按时间片执行逻辑
            this.realTime += deltaTime;
            while (realTime - this.currentTime > DELTA_TIME)
            {
                this.currentTime += DELTA_TIME;
                rounding = DoUpdate(DELTA_TIME);
                if (rounding == false)
                    break;
            }
            return true;
        }

        public bool DoUpdate(double deltaTime)
        {
            if (this.end == true)
                return false;

            if (rounding == false)
                return false;

            //ai
            if (this.data.curRoundCamp == CampType.ATTACK)
            {
                if (attackerAI != null && attackerAuto == true)
                {
                    attackerAI.Update(deltaTime);
                }
            }
            else
            {
                if (defenderAI != null && defenderAuto == true)
                {
                    defenderAI.Update(deltaTime);
                }
            }

            //战斗逻辑
            data.exports.Clear();       //清除缓存数据

            this.data.attacker.Update(this.data);
            this.data.defender.Update(this.data);

            if (this.data.callback != null)
                this.data.callback.Tick(data.exports);

            //是否需要自动退出
            if (this.autoFinishARound == true)
            {
                bool canFinish = true;
                foreach (var actor in this.data.curPlayer.actors)
                {
                    foreach (var skill in actor.skills)
                    {
                        if (skill.state == FSkillState.WAIT || skill.state == FSkillState.DOING)
                        {
                            canFinish = false;
                            break;
                        }
                    }
                    if (canFinish == false)
                        break;
                }

                if (canFinish == true)
                {
                    FinishRound();
                }
            }

            data.roundTime += deltaTime;

            return true;
        }

        //内部回调,战斗开始
        public override void BattleBegin()
        {
            //通知战斗开始
            if(this.data.callback != null)
                this.data.callback.BattleBegin(data.curRoundCamp);
            //处理战斗开始时的buff
            foreach(var actor in this.data.attacker.actors)
            {
                if (actor.state != FActorState.DEAD)
                {
                    actor.buffProc.LoadBuffByTimer(TalentBuffTriggerTimer.FightBegin);
                }
            }
            foreach (var actor in this.data.defender.actors)
            {
                if (actor.state != FActorState.DEAD)
                {
                    actor.buffProc.LoadBuffByTimer(TalentBuffTriggerTimer.FightBegin);
                }
            }
        }

        //内部回调,战斗结束,战斗结果
        public override void BattleEnd()
        {
            Debug.LogFightMsg100("--------result, round=" + data.roundNum + ", numhp1=" + data.GetNumHP(CampType.ATTACK) + ", numhp2=" + data.GetNumHP(CampType.DEFENCE));
            Debug.LogFightMsg("--------result, round=" + data.roundNum + ", numhp1=" + data.GetNumHP(CampType.ATTACK) + ", numhp2=" + data.GetNumHP(CampType.DEFENCE));

            this.end = true;
            if (this.data.callback != null)
                this.data.callback.BattleEnd(data);
        }

        //内部回调,回合开始
        public override void RoundBegin()
        {
            //通知回合开始
            if(this.data.callback != null)
                this.data.callback.RoundBegin(this.data.roundNum, data.curRoundCamp, this.data);
            data.exports.Clear();
            bool hasAttacker = false;
            bool hasDefender = false;
            if (data.curRoundCamp == CampType.ATTACK)
            {
                //处理战斗中回合开始时的buff
                foreach (var actor in this.data.attacker.actors)
                {
                    if(actor.state != FActorState.DEAD)
                    {
                        hasAttacker = true;
                        actor.buffProc.LoadBuffByTimer(TalentBuffTriggerTimer.SelfRoundBegin);
                        actor.buffManager.ProcMyRoundStart();
                        actor.attribute.magicStoneNum = 0;
                        Debug.LogFightMsg("----round:"+data.roundNum+"----round begin:ATTACK Anger"+ actor.player.angerNum + "-----hero:" + actor.heroId + "-----HP:"+ actor .attribute.hp);
                    }
                    else
                    {//死亡后的人可能有额外的buff
                        actor.buffManager.ProcMyRoundStart();
                    }
                }
                foreach (var actor in this.data.defender.actors)
                {
                    if (actor.state != FActorState.DEAD)
                    {
                        hasDefender = true;
                        actor.buffProc.LoadBuffByTimer(TalentBuffTriggerTimer.EnemyRoundBegin);
                        actor.attribute.magicStoneNum = 0;
                        Debug.LogFightMsg("----round:" + data.roundNum + "----round begin:DEFENCE Anger" + actor.player.angerNum + "-----hero:" + actor.heroId + "-----HP:" + actor.attribute.hp);
                    }
                }
            }
            else
            {
                //处理战斗中回合开始时的buff
                foreach (var actor in this.data.defender.actors)
                {
                    if (actor.state != FActorState.DEAD)
                    {
                        hasDefender = true;
                        actor.buffProc.LoadBuffByTimer(TalentBuffTriggerTimer.SelfRoundBegin);
                        actor.buffManager.ProcMyRoundStart();
                        actor.attribute.magicStoneNum = 0;
                        Debug.LogFightMsg("----round:" + data.roundNum + "----round begin:ATTACK Anger" + actor.player.angerNum + "-----hero:" + actor.heroId + "-----HP:" + actor.attribute.hp);
                    }
                    else
                    {//死亡后的人可能有额外的buff
                        actor.buffManager.ProcMyRoundStart();
                    }
                }
                foreach (var actor in this.data.attacker.actors)
                {
                    if (actor.state != FActorState.DEAD)
                    {
                        hasAttacker = true;
                        actor.buffProc.LoadBuffByTimer(TalentBuffTriggerTimer.EnemyRoundBegin);
                        actor.attribute.magicStoneNum = 0;
                        Debug.LogFightMsg("----round:" + data.roundNum + "----round begin:DEFENCE Anger" + actor.player.angerNum + "-----hero:" + actor.heroId + "-----HP:" + actor.attribute.hp);
                    }
                }
            }

            if (hasAttacker == false || hasDefender == false)
            {
                BattleEnd();
                return;
            }

            if (this.data.callback != null)
                this.data.callback.RoundBeginTick(data.exports);

            //如果没有可使用的普通技能,表示计入回合结束的倒计时
            if (HasActiveNormalSkill() == false)
            {
                NotifyCanFinishRound();
            }

        }

        //内部回调,回合结束
        public override void RoundEnd()
        {
            data.exports.Clear();
            //处理技能冷却，以及buff回合更新
            foreach (var actor in this.data.attacker.actors)
            {
                //处理技能冷却更新 （由于可能会复活，死亡的人也需要处理）
                foreach (var skill in actor.skills)
                {
                    skill.cooldownCur--;
                    if (skill.cooldownCur <= 0)
                        skill.cooldownCur = 0;
                }
                if (actor.state == FActorState.WAEKDEAD || actor.state == FActorState.DEAD)
                {
                    if (actor.state != FActorState.DEAD)
                        actor.state = FActorState.DEAD;
                    continue;
                }
                if (data.curRoundCamp == CampType.ATTACK)
                {
                    actor.buffManager.ProcMyRoundEnd();
                }
                //处理回合buff更新
                actor.buffManager.RoundEnd();
            }

            foreach (var actor in this.data.defender.actors)
            {
                //处理技能冷却更新 （由于可能会复活，死亡的人也需要处理）
                foreach (var skill in actor.skills)
                {
                    skill.cooldownCur--;
                    if (skill.cooldownCur <= 0)
                        skill.cooldownCur = 0;
                }
                if (actor.state == FActorState.WAEKDEAD || actor.state == FActorState.DEAD)
                {
                    if (actor.state != FActorState.DEAD)
                        actor.state = FActorState.DEAD;
                    continue;
                }
                if (data.curRoundCamp == CampType.DEFENCE)
                {
                    actor.buffManager.ProcMyRoundEnd();
                }
                //处理回合buff更新
                actor.buffManager.RoundEnd();
            }

            //切换回合出手
            if (data.curRoundCamp == CampType.ATTACK)
            {
                data.curRoundCamp = CampType.DEFENCE;
                data.curPlayer = data.defender;
            }
            else
            {
                data.curRoundCamp = CampType.ATTACK;
                data.curPlayer = data.attacker;
            }

            if (this.data.callback != null)
                this.data.callback.RoundEndTick(data.exports);
            //通知回合结束
            if (this.data.callback != null)
                this.data.callback.RoundEnd(data.curRoundCamp);
        }

        //内部回调,技能开始
        public override void SkillBegin(FSkill skill, List<FActor> targets)
        {
            //通知技能开始
            if (this.data.callback != null)
                this.data.callback.SkillBegin(skill, targets);
        }

        //内部回调,技能结束
        public override void SkillEnd(CampType camp, string uniquedId, FSkill skill)
        {
            //通知技能结束
            if (this.data.callback != null)
                this.data.callback.SkillEnd(camp, uniquedId, skill.index, skill);
            
            //如果没有可使用的普通技能,表示计入回合结束的倒计时
            if (HasActiveNormalSkill() == false)
            {
                NotifyCanFinishRound();
            }
        }

        //内部回调,技能伤害
        public override void SkillCast(FRelease release)
        {

        }

        //内部回调,技能发射
        public override void SkillProject(FRelease release)
        {

        }

        //内部回调,Actor进入死亡状态
        public override void ActorDead(FActor actor)
        {
            if (TestBattleEnd() == true)
            {
                BattleEnd();
            }
        }

        public override void NotifyCanFinishRound()
        {
            if (this.data.callback != null)
                this.data.callback.HaventActiveNormalSkill();
        }


        //当前是否有激活的普通技能,如果都没有表示计入回合结束的倒计时
        public override bool HasActiveNormalSkill()
        {
            FPlayer player = this.data.GetCurRoundPlayer();
            foreach (var actor in player.actors)
            {
                if (actor.state == FActorState.WAEKDEAD || actor.state == FActorState.DEAD)
                {
                    continue;
                }
                foreach (var skill in actor.skills)
                {
                    if (skill.IsUltimate == false)
                    {
                        if (actor.isActive(skill) == true || actor.isCanDoSkill(skill))
                            return true;
                    }
                }
            }
            return false;
        }
        
        public override void SetBuffsAtBattleBegin(CampType camp, List<string> buffIds)
        {
            FPlayer player = this.data.getPlayerByCampType(camp);
            foreach(string buffId in buffIds)
            {
                foreach (FActor actor in player.actors)
                {
                    if(actor.state != FActorState.DEAD)
                    {
                        Buff buff = FBuffFactory.CreateBuff(buffId, this.data).Clone();
                        buff.LoadBuff(actor, TalentBuffTriggerTimer.FightBegin);
                    }
                }
            }
        }

        //判断战斗是否结束,如果战斗结束,返回消息
        //一方都死即战斗结束
        public bool TestBattleEnd()
        {
            bool hasAttacker = false;
            bool hasDefender = false;
            foreach (var actor in data.attacker.actors)
            {
                if (actor.state != FActorState.DEAD)
                {
                    hasAttacker = true;
                    break;
                }
            }

            foreach (var actor in data.defender.actors)
            {
                if (actor.state != FActorState.DEAD)
                {
                    hasDefender = true;
                    break;
                }
            }

            if (hasAttacker == false || hasDefender == false)
                return true;
            return false;
        }

        //跳过
        public override void Skip()
        {
            //EngineAICallback callback = new EngineAICallback();
            //callback.compute = this;
            if (attackerAI != null)
            {
                //attackerAI.SetCallback(callback);
                SetAuto(CampType.ATTACK, true);
            }
            if (defenderAI != null)
            {
                //defenderAI.SetCallback(callback);
                SetAuto(CampType.DEFENCE, true);
            }

            isSkipping = true;
            for (int i = 0; i < 100; ++i)
            {
                double maxTime = 1000;
                Update(maxTime);
                if (end == true)
                    break;
                NextRound();
                if (end == true)
                    break;
            }
            isSkipping = false;

            //int aa = 0;
        }

        //跳过大招
        public override void SkipUltimate()
        {
            if (data.ultimateSkill == null)
                return;
            if (data.roundTime >= data.ultimateSkill.skipTime)
                return;

            double time = data.ultimateSkill.skipTime - data.roundTime;
            Update(time);
            if (this.data.callback != null)
                this.data.callback.SkipUltimate();
        }

        //设置技能开关
        public override void SetSkill(CampType camp, string uniquedId, int skillIndex, bool enbale)
        {
            if (camp == CampType.ATTACK)
            {
                foreach (var actor in data.attacker.actors)
                {
                    if (actor.uniqueId.Equals(uniquedId) == true)
                    {
                        actor.SetSkill(skillIndex, enbale);
                        break;
                    }
                }
            }
            else if (camp == CampType.DEFENCE)
            {
                foreach (var actor in data.defender.actors)
                {
                    if (actor.uniqueId.Equals(uniquedId) == true)
                    {
                        actor.SetSkill(skillIndex, enbale);
                        break;
                    }
                }
            }
        }

        //设置AI,只对真实战斗有效
        public override void SetAI(CampType camp, AI.EngineAI ai)
        {
            if (camp == CampType.ATTACK)
            {
                attackerAI = ai;
                EngineAICallback callback = new EngineAICallback();
                callback.compute = this;
                attackerAI.SetCallback(callback);
            }
            else
            {
                defenderAI = ai;
                EngineAICallback callback = new EngineAICallback();
                callback.compute = this;
                defenderAI.SetCallback(callback);
            }
        }

        //设置是否使用AI自动操作
        public override void SetAuto(CampType camp, bool auto)
        {
            if (camp == CampType.ATTACK)
            {
                attackerAuto = auto;
                if (attackerAI != null && data.curRoundCamp == CampType.ATTACK)
                {
                    if (attackerAuto)
                        attackerAI.Run();
                    else
                        attackerAI.StopRun();
                }
            }
            else
            {
                defenderAuto = auto;
                if (defenderAI != null && data.curRoundCamp == CampType.DEFENCE)
                {
                    if (defenderAuto)
                        defenderAI.Run();
                    else
                        defenderAI.StopRun();
                }
            }
        }

        public override bool IsAuto(CampType camp)
        {
            if (camp == CampType.ATTACK)
            {
                return attackerAuto;
            }
            else
            {
                return defenderAuto;
            }
        }

        //在没有技能发动中的时候回合结束, 只有当前回合有效
        public override void AutoFinishARound()
        {
            this.autoFinishARound = true;
        }

        public override EngineData GetEngineData()
        {
            return this.data;
        }

        public override bool IsSkipping()
        {
            return isSkipping;
        }
    }
}
